Izpētiet React useActionState āķi, lai optimizētu stāvokļa pārvaldību, ko ierosina asinhronas darbības. Uzlabojiet savas lietotnes efektivitāti un lietotāja pieredzi.
React useActionState ieviešana: uz darbībām balstīta stāvokļa pārvaldība
React useActionState āķis, kas ieviests jaunākajās versijās, piedāvā pilnveidotu pieeju stāvokļa atjauninājumu pārvaldībai, kas rodas no asinhronām darbībām. Šis jaudīgais rīks optimizē mutāciju apstrādes, lietotāja saskarnes (UI) atjaunināšanas un kļūdu stāvokļu pārvaldības procesu, īpaši strādājot ar React Servera Komponentēm (RSC) un servera darbībām. Šajā rokasgrāmatā tiks pētītas useActionState nianses, sniedzot praktiskus piemērus un labākās prakses tā ieviešanai.
Izpratne par nepieciešamību pēc uz darbībām balstītas stāvokļa pārvaldības
Tradicionālā React stāvokļa pārvaldība bieži ietver ielādes un kļūdu stāvokļu atsevišķu pārvaldību komponentēs. Kad darbība (piemēram, veidlapas iesniegšana, datu ielāde) izraisa stāvokļa atjauninājumu, izstrādātāji parasti pārvalda šos stāvokļus ar vairākiem useState izsaukumiem un potenciāli sarežģītu nosacījumu loģiku. useActionState nodrošina tīrāku un integrētāku risinājumu.
Apsveriet vienkāršu veidlapas iesniegšanas scenāriju. Bez useActionState jums varētu būt:
- Stāvokļa mainīgais veidlapas datiem.
- Stāvokļa mainīgais, lai sekotu līdzi, vai veidlapa tiek iesniegta (ielādes stāvoklis).
- Stāvokļa mainīgais, lai saglabātu jebkādus kļūdu ziņojumus.
Šī pieeja var novest pie gari izvērsta koda un iespējamām nekonsekvencēm. useActionState konsolidē šīs problēmas vienā āķī, vienkāršojot loģiku un uzlabojot koda lasāmību.
Iepazīstinām ar useActionState
useActionState āķis pieņem divus argumentus:
- Asinhronu funkciju ("darbību"), kas veic stāvokļa atjaunināšanu. Tā var būt servera darbība vai jebkura asinhrona funkcija.
- Sākotnējo stāvokļa vērtību.
Tas atgriež masīvu, kas satur divus elementus:
- Pašreizējo stāvokļa vērtību.
- Funkciju, lai izsauktu darbību. Šī funkcija automātiski pārvalda ielādes un kļūdu stāvokļus, kas saistīti ar darbību.
Šeit ir pamata piemērs:
import { useActionState } from 'react';
async function updateServer(prevState, formData) {
// Simulējam asinhronu servera atjauninājumu.
await new Promise(resolve => setTimeout(resolve, 1000));
const data = Object.fromEntries(formData);
if (data.name === "error") {
return 'Neizdevās atjaunināt serveri.';
}
return `Vārds atjaunināts uz: ${data.name}`;
}
function MyComponent() {
const [state, dispatch] = useActionState(updateServer, 'Sākotnējais stāvoklis');
async function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
const result = await dispatch(formData);
console.log(result);
}
return (
);
}
Šajā piemērā:
updateServerir asinhrona darbība, kas simulē servera atjaunināšanu. Tā saņem iepriekšējo stāvokli un veidlapas datus.useActionStateinicializē stāvokli ar 'Sākotnējais stāvoklis' un atgriež pašreizējo stāvokli undispatchfunkciju.handleSubmitfunkcija izsaucdispatchar veidlapas datiem.useActionStateautomātiski apstrādā ielādes un kļūdu stāvokļus darbības izpildes laikā.
Ielādes un kļūdu stāvokļu apstrāde
Viena no galvenajām useActionState priekšrocībām ir tā iebūvētā ielādes un kļūdu stāvokļu pārvaldība. dispatch funkcija atgriež solījumu (promise), kas atrisinās ar darbības rezultātu. Ja darbība izraisa kļūdu, solījums tiek noraidīts ar kļūdu. Jūs varat to izmantot, lai atbilstoši atjauninātu UI.
Pārveidosim iepriekšējo piemēru, lai parādītu ielādes ziņojumu un kļūdas ziņojumu:
import { useActionState } from 'react';
import { useState } from 'react';
async function updateServer(prevState, formData) {
// Simulējam asinhronu servera atjauninājumu.
await new Promise(resolve => setTimeout(resolve, 1000));
const data = Object.fromEntries(formData);
if (data.name === "error") {
throw new Error('Neizdevās atjaunināt serveri.');
}
return `Vārds atjaunināts uz: ${data.name}`;
}
function MyComponent() {
const [state, dispatch] = useActionState(updateServer, 'Sākotnējais stāvoklis');
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
async function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
setIsSubmitting(true);
setErrorMessage(null);
try {
const result = await dispatch(formData);
console.log(result);
} catch (error) {
console.error("Kļūda iesniegšanas laikā:", error);
setErrorMessage(error.message);
} finally {
setIsSubmitting(false);
}
}
return (
);
}
Galvenās izmaiņas:
- Mēs pievienojām
isSubmittingunerrorMessagestāvokļa mainīgos, lai sekotu līdzi ielādes un kļūdu stāvokļiem. handleSubmitfunkcijā mēs iestatāmisSubmittinguztruepirmsdispatchizsaukšanas un notveram jebkādas kļūdas, lai atjauninātuerrorMessage.- Mēs atspējojam iesniegšanas pogu, kamēr notiek iesniegšana, un nosacīti parādām ielādes un kļūdu ziņojumus.
useActionState ar servera darbībām React Servera Komponentēs (RSC)
useActionState īpaši labi darbojas, ja to lieto kopā ar React Servera Komponentēm (RSC) un servera darbībām. Servera darbības ir funkcijas, kas darbojas serverī un var tieši mainīt datu avotus. Tās ļauj veikt servera puses operācijas, nerakstot API galapunktus.
Piezīme: Šim piemēram ir nepieciešama React vide, kas konfigurēta Servera Komponentēm un Servera Darbībām.
// app/actions.js (Servera darbība)
'use server';
import { cookies } from 'next/headers'; //Piemērs, priekš Next.js
export async function updateName(prevState, formData) {
const name = formData.get('name');
if (!name) {
return 'Lūdzu, ievadiet vārdu.';
}
try {
// Simulējam datubāzes atjaunināšanu.
await new Promise(resolve => setTimeout(resolve, 1000));
cookies().set('userName', name);
return `Vārds atjaunināts uz: ${name}`; //Veiksmīgi!
} catch (error) {
console.error("Datubāzes atjaunināšana neizdevās:", error);
return 'Neizdevās atjaunināt vārdu.'; // Svarīgi: Atgriezt ziņojumu, nevis izmest kļūdu (Error)
}
}
// app/page.jsx (React Servera Komponente)
'use client';
import { useActionState } from 'react';
import { updateName } from './actions';
function MyComponent() {
const [state, dispatch] = useActionState(updateName, 'Sākotnējais stāvoklis');
async function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
const result = await dispatch(formData);
console.log(result);
}
return (
);
}
export default MyComponent;
Šajā piemērā:
updateNameir servera darbība, kas definētaapp/actions.js. Tā saņem iepriekšējo stāvokli un veidlapas datus, atjaunina datubāzi (simulēti) un atgriež veiksmes vai kļūdas ziņojumu. Būtiski, ka darbība atgriež ziņojumu, nevis izraisa kļūdu. Servera darbībās priekšroka tiek dota informatīvu ziņojumu atgriešanai.- Komponents ir atzīmēts kā klienta komponents (
'use client'), lai izmantotuuseActionStateāķi. handleSubmitfunkcija izsaucdispatchar veidlapas datiem.useActionStateautomātiski pārvalda stāvokļa atjaunināšanu, pamatojoties uz servera darbības rezultātu.
Svarīgi apsvērumi servera darbībām
- Kļūdu apstrāde servera darbībās: Tā vietā, lai izmestu kļūdas, atgrieziet no savas Servera Darbības nozīmīgu kļūdas ziņojumu.
useActionStateuztvers šo ziņojumu kā jauno stāvokli. Tas ļauj graciozi apstrādāt kļūdas klienta pusē. - Optimistiskie atjauninājumi: Servera darbības var izmantot ar optimistiskiem atjauninājumiem, lai uzlabotu uztverto veiktspēju. Jūs varat nekavējoties atjaunināt UI un atsaukt izmaiņas, ja darbība neizdodas.
- Pārvalidēšana (Revalidation): Pēc veiksmīgas mutācijas apsveriet kešoto datu pārvalidēšanu, lai nodrošinātu, ka UI atspoguļo jaunāko stāvokli.
Papildu useActionState tehnikas
1. Reduktora (Reducer) izmantošana sarežģītiem stāvokļa atjauninājumiem
Sarežģītākai stāvokļa loģikai varat apvienot useActionState ar reduktora funkciju. Tas ļauj pārvaldīt stāvokļa atjauninājumus paredzamā un uzturamā veidā.
import { useActionState } from 'react';
import { useReducer } from 'react';
const initialState = {
count: 0,
message: 'Sākotnējais stāvoklis',
};
function reducer(state, action) {
switch (action.type) {
case 'INCREMENT':
return { ...state, count: state.count + 1 };
case 'DECREMENT':
return { ...state, count: state.count - 1 };
case 'SET_MESSAGE':
return { ...state, message: action.payload };
default:
return state;
}
}
async function updateState(state, action) {
// Simulējam asinhronu operāciju.
await new Promise(resolve => setTimeout(resolve, 500));
switch (action.type) {
case 'INCREMENT':
return reducer(state, action);
case 'DECREMENT':
return reducer(state, action);
case 'SET_MESSAGE':
return reducer(state, action);
default:
return state;
}
}
function MyComponent() {
const [state, dispatch] = useActionState(updateState, initialState);
return (
Skaits: {state.count}
Ziņojums: {state.message}
);
}
2. Optimistiskie atjauninājumi ar useActionState
Optimistiskie atjauninājumi uzlabo lietotāja pieredzi, nekavējoties atjauninot UI tā, it kā darbība būtu bijusi veiksmīga, un pēc tam atceļot atjauninājumu, ja darbība neizdodas. Tas var padarīt jūsu lietotni atsaucīgāku.
import { useActionState } from 'react';
import { useState } from 'react';
async function updateServer(prevState, formData) {
// Simulējam asinhronu servera atjauninājumu.
await new Promise(resolve => setTimeout(resolve, 1000));
const data = Object.fromEntries(formData);
if (data.name === "error") {
throw new Error('Neizdevās atjaunināt serveri.');
}
return `Vārds atjaunināts uz: ${data.name}`;
}
function MyComponent() {
const [name, setName] = useState('Sākotnējais vārds');
const [state, dispatch] = useActionState(async (prevName, newName) => {
try {
const result = await updateServer(prevName, {
name: newName,
});
return newName; // Atjaunināt pēc veiksmīgas izpildes
} catch (error) {
// Atcelt kļūdas gadījumā
console.error("Atjaunināšana neizdevās:", error);
setName(prevName);
return prevName;
}
}, name);
async function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
const newName = formData.get('name');
setName(newName); // Optimistiski atjaunināt UI
await dispatch(newName);
}
return (
);
}
3. Darbību atlikšana (Debouncing)
Dažos scenārijos jūs varētu vēlēties atlikt darbības, lai novērstu to pārāk biežu izsaukšanu. Tas var būt noderīgi tādiem scenārijiem kā meklēšanas ievades lauki, kur darbību vēlaties aktivizēt tikai pēc tam, kad lietotājs ir pārtraucis rakstīt uz noteiktu laiku.
import { useActionState } from 'react';
import { useState, useEffect } from 'react';
async function searchItems(prevState, query) {
// Simulējam asinhronu meklēšanu.
await new Promise(resolve => setTimeout(resolve, 500));
return `Meklēšanas rezultāti vaicājumam: ${query}`;
}
function MyComponent() {
const [query, setQuery] = useState('');
const [state, dispatch] = useActionState(searchItems, 'Sākotnējais stāvoklis');
useEffect(() => {
const timeoutId = setTimeout(() => {
if (query) {
dispatch(query);
}
}, 300); // Atlikt par 300ms
return () => clearTimeout(timeoutId);
}, [query, dispatch]);
return (
setQuery(e.target.value)}
/>
Stāvoklis: {state}
);
}
Labākā prakse useActionState lietošanā
- Uzturiet darbības tīras (Pure): Pārliecinieties, ka jūsu darbības ir tīras funkcijas (vai pēc iespējas tuvākas tam). Tām nevajadzētu būt blakusefektiem, izņemot stāvokļa atjaunināšanu.
- Apstrādājiet kļūdas graciozi: Vienmēr apstrādājiet kļūdas savās darbībās un sniedziet lietotājam informatīvus kļūdu ziņojumus. Kā minēts iepriekš saistībā ar Servera Darbībām, dodiet priekšroku kļūdas ziņojuma virknes atgriešanai no servera darbības, nevis kļūdas izmešanai.
- Optimizējiet veiktspēju: Esiet uzmanīgi attiecībā uz savu darbību veiktspējas ietekmi, īpaši strādājot ar lieliem datu apjomiem. Apsveriet memoizācijas tehniku izmantošanu, lai izvairītos no nevajadzīgiem pārzīmēšanas gadījumiem (re-renders).
- Apsveriet pieejamību: Nodrošiniet, lai jūsu lietotne būtu pieejama visiem lietotājiem, ieskaitot tos ar invaliditāti. Nodrošiniet atbilstošus ARIA atribūtus un tastatūras navigāciju.
- Rūpīga testēšana: Rakstiet vienības testus un integrācijas testus, lai nodrošinātu, ka jūsu darbības un stāvokļa atjauninājumi darbojas pareizi.
- Internacionalizācija (i18n): Globālām lietotnēm ieviesiet i18n, lai atbalstītu vairākas valodas un kultūras.
- Lokalizācija (l10n): Pielāgojiet savu lietotni konkrētiem reģioniem, nodrošinot lokalizētu saturu, datumu formātus un valūtas simbolus.
useActionState salīdzinājumā ar citiem stāvokļa pārvaldības risinājumiem
Lai gan useActionState nodrošina ērtu veidu, kā pārvaldīt uz darbībām balstītus stāvokļa atjauninājumus, tas neaizstāj visus stāvokļa pārvaldības risinājumus. Sarežģītām lietotnēm ar globālu stāvokli, kas jākoplieto starp vairākām komponentēm, piemērotākas varētu būt tādas bibliotēkas kā Redux, Zustand vai Jotai.
Kad lietot useActionState:
- Vienkāršas līdz vidēji sarežģītas stāvokļa atjaunināšanas.
- Stāvokļa atjauninājumi, kas cieši saistīti ar asinhronām darbībām.
- Integrācija ar React Servera Komponentēm un Servera Darbībām.
Kad apsvērt citus risinājumus:
- Sarežģīta globālā stāvokļa pārvaldība.
- Stāvoklis, kas jākoplieto starp lielu skaitu komponenšu.
- Papildu funkcijas, piemēram, laika ceļojumu atkļūdošana (time-travel debugging) vai starpprogrammatūra (middleware).
Noslēgums
React useActionState āķis piedāvā jaudīgu un elegantu veidu, kā pārvaldīt stāvokļa atjauninājumus, ko ierosina asinhronas darbības. Konsolidējot ielādes un kļūdu stāvokļus, tas vienkāršo kodu un uzlabo lasāmību, īpaši strādājot ar React Servera Komponentēm un servera darbībām. Izpratne par tā stiprajām un vājajām pusēm ļauj jums izvēlēties pareizo stāvokļa pārvaldības pieeju jūsu lietotnei, kas noved pie uzturamāka un efektīvāka koda.
Ievērojot šajā rokasgrāmatā izklāstītās labākās prakses, jūs varat efektīvi izmantot useActionState, lai uzlabotu savas lietotnes lietotāja pieredzi un izstrādes darbplūsmu. Atcerieties ņemt vērā savas lietotnes sarežģītību un izvēlēties stāvokļa pārvaldības risinājumu, kas vislabāk atbilst jūsu vajadzībām. No vienkāršām veidlapu iesniegšanām līdz sarežģītām datu mutācijām, useActionState var būt vērtīgs rīks jūsu React izstrādes arsenālā.